﻿using System;
using System.Collections.Generic;

namespace Teal.Compiler {

    #region Statement

    /// <summary>
    /// 表示一个语法树节点。
    /// </summary>
    public abstract partial class Node {

        /// <summary>
        /// 报告当前节点不可访问的警告。
        /// </summary>
        /// <returns>如果已输出警告信息则返回 true，否则返回 false。</returns>
        public virtual bool reportUnreachableCodeWarning() {
            Compiler.warning(ErrorCode.none, "检测到永远不会执行的代码", this);
            return true;
        }

    }

    /// <summary>
    /// 表示一个变量。
    /// </summary>
    public partial class Variable : Node {

        /// <summary>
        /// 获取当前变量引用的在当前函数内的索引。如果返回 0，表示此变量是编译器动态生成的。
        /// </summary>
        public int index;

        /// <summary>
        /// 判断或设置当前变量是否已声明。on: 已声明；off：未声明，但存在命名冲突；unset：未声明。
        /// </summary>
        [fieldAutoMerged]
        public State declareState;

        /// <summary>
        /// 判断当前变量是否有过赋值操作。
        /// </summary>
        [fieldAutoMerged]
        public bool isEverAssigned;

        /// <summary>
        /// 判断当前变量是否已被使用。
        /// </summary>
        [fieldAutoMerged]
        public bool isEverUsed;

        /// <summary>
        /// 获取当前变量的类型引用。
        /// </summary>
        public TypeReference resolvedType;

        /// <summary>
        /// 标记指定的变量为已赋值。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public void setAssigned(ResolveContext context) {

            // 在流程分支标记当前变量已赋值。
            if (index > 0 && !context.currentFlowControl.currentBranching.isJumped) {
                context.currentFlowControl.currentBranching.setAssigned(index);
            }

            // 存储曾经赋值过。
            isEverAssigned = true;

        }

        /// <summary>
        /// 判断在指定的解析上下文中，变量是否已赋值。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns></returns>
        public bool isAssigned(ResolveContext context) {

            // 如果当前分支已跳转，则不继续判断变量赋值情况。
            return index == 0 || context.currentFlowControl.currentBranching.isJumped || context.currentFlowControl.currentBranching.isAssigned(index);
        }

        /// <summary>
        /// 对当前节点执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <param name="ignoreVar">是否忽略更新当前变量的 var 类型。</param>
        public void resolve(ResolveContext context, bool ignoreVar = false) {

            // 解析变量类型。
            if (type != null) {
                resolvedType = type.resolveAsType(context.currentMemberDefinition, MemberUsage.type);
            }

            if (resolvedType != null) {
                ResolveHelper.checkVaribaleType(resolvedType, type);
            } else {
                resolvedType = PredefinedTypes.var;
            }

            // 解析变量名。
            // 当前变量名可能在上级范围或子级范围定义。
            // 首先查找当前变量在子级返回和父级范围是否存在同名定义，
            // 如果存在，则根据变量的出现顺序，应对后出现的变量报错。

            if (declareState == State.off) {
                Compiler.error(ErrorCode.none, String.Format("无法定义局部变量“{0}”, 因为在子级范围已经定义了同名的局部变量", name.value), name);
            } else {
                for (var c = context.currentFlowControl; c != null; c = c.parentControl) {
                    var variable = c.getVariable(name.value);
                    if (variable != null && variable != this) {

                        // 如果变量已解析，说明上级变量在前，当前变量在后。
                        // 否则说明当前变量在前，上级变量先标记，等待解析上级变量时报错。
                        if (variable.declareState == State.on) {
                            Compiler.error(ErrorCode.none, String.Format("无法定义局部变量“{0}”, 因为在当前范围或父级范围内经定义了同名的局部变量", name.value), name);
                        } else {
                            variable.declareState = State.off;
                        }
                    }
                }
            }

            // 标记解析。
            declareState = State.on;

            // 解析初始化值。
            if (initialiser != null) {
                initialiser = initialiser.resolveAsValue(context, ref resolvedType);
                setAssigned(context);
            } else if (!ignoreVar && resolvedType == PredefinedTypes.var) {
                ResolveHelper.reportVarAsDynamicError(type);
                resolvedType = PredefinedTypes.@dynamic;
            }

        }

    }

    /// <summary>
    /// 表示一个函数参数。
    /// </summary>
    public partial class Parameter : Variable {

        ///// <summary>
        ///// 当前参数在所属定义中的位置。
        ///// </summary>
        //public int parameterIndex = 0;

    }

    /// <summary>
    /// 表示一个语句。
    /// </summary>
    public abstract partial class Statement : Node {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public abstract void resolve(ResolveContext context);

    }

    /// <summary>
    /// 表示一个空语句。
    /// </summary>
    public partial class Semicolon {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public override void resolve(ResolveContext context) { }

    }

    #endregion

    #region Blocks

    /// <summary>
    /// 表示一个语句块。
    /// </summary>
    public partial class Block {

        /// <summary>
        /// 报告当前节点不可访问的警告。
        /// </summary>
        /// <returns>如果已输出警告信息则返回 true，否则返回 false。</returns>
        public override bool reportUnreachableCodeWarning() {
            if (statements != null) {
                for (int i = 0; i < statements.Count; i++) {
                    if (statements[i].reportUnreachableCodeWarning()) {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 当前块内所有标签。
        /// </summary>
        Dictionary<string, LabeledStatement> _labels;

        /// <summary>
        /// 获取当前块内指定名字的第一个标签语句。
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public LabeledStatement getLabel(string name) {
            LabeledStatement result;
            return _labels != null && _labels.TryGetValue(name, out result) ? result : null;
        }

        /// <summary>
        /// 记录当前语句块内是否跳转了。
        /// </summary>
        public bool isJumped;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {

            // 忽略空语句。
            if (statements == null) {
                return;
            }

            // 进入执行分支。
            context.enterFlowControl(new BlockFlowControl(context.currentFlowControl, this));

            // 初始化内部的标签和变量列表。
            for (int i = 0; i < statements.Count; i++) {
                var s = statements[i];

                var vs = s as VariableStatement;
                if (vs != null) {
                    context.addVariables(vs.variables);
                }

                var ls = s as LabeledStatement;
                if (ls != null) {

                    // 嵌套标签语句需要拆为两个。因为之后的逻辑标签语句只能为独立语句。
                    if (ls.body is LabeledStatement) {
                        statements.Insert(i + 1, ls.body);
                        ls.body = null;
                    }

                    if (_labels == null) {
                        _labels = new Dictionary<string, LabeledStatement>();
                    } else if (_labels.ContainsKey(ls.label.value)) {
                        continue;
                    }

                    _labels[ls.label.value] = ls;
                }
            }

            // 解析所有语句。
            bool wasNotJumped = !context.currentFlowControl.currentBranching.isJumped;

            for (int i = 0, len = statements.Count; i < len; i++) {

                // 任何一个跳转语句都会导致之后的语句不可执行。
                // 如果之后的语句不存在标签语句，则这些语句永远不可执行。
                // 但如果之后的语句有标签语句，则它们可能因为其它 goto 语句重新激活。
                // 此时的执行策略为：每次找出被 goto 激活的标签语句并执行，
                // 最后未被激活的标签语句被认为是不可执行的。

                // 判断之前的语句是否已跳出，如果已跳出则之后的语句不能正常执行。
                if (context.currentFlowControl.currentBranching.isJumped) {

                    // 没有标签语句，接下来的所有语句都是不可访问的。
                    if (_labels == null) {

                        for (; i < len; i++) {
                            if (wasNotJumped && statements[i].reportUnreachableCodeWarning()) {
                                wasNotJumped = false;
                            }
                            statements[i].resolve(context);
                        }

                        // 一切操作完成，直接退出即可。
                        break;
                    }

                    // 存在标签语句，依次扫描被 goto 激活的语句并执行。
                    // 所有语句执行完后，重新扫描列表。剩下的语句都是不可执行的。
                    Statement[] left = new Statement[len - i];
                    statements.CopyTo(i, left, 0, left.Length);

                    // 标记是否有新的语句被重新执行。
                    bool hasNewLabelReached;

                    do {
                        hasNewLabelReached = false;
                        for (int j = 0; j < left.Length; j++) {
                            LabeledStatement ls = left[j] as LabeledStatement;
                            if (ls != null && ls.isEverUsed) {
                                hasNewLabelReached = true;

                                // 依次执行之后的语句直到重新跳转或语句结束。
                                do {

                                    // 执行语句。
                                    left[j].resolve(context);

                                    // 清空已执行的语句。
                                    left[j] = null;

                                } while (++j < left.Length && left[j] != null && !context.currentFlowControl.currentBranching.isJumped);

                            }
                        }
                    } while (hasNewLabelReached);

                    // 所有能执行的语句都执行完毕，剩下的是不能执行的语句，报告不可访问的错误。
                    for (int j = 0; j < left.Length; j++) {
                        if (left[j] != null) {
                            if (wasNotJumped && left[j].reportUnreachableCodeWarning()) {
                                wasNotJumped = false;
                            }
                            left[j].resolve(context);
                        }
                    }

                    // 一切操作完成，直接退出即可。
                    break;

                }

                // 执行语句本身。
                statements[i].resolve(context);

            }

            // 退出执行分支。

            // 退出所有的标签分支。
            while (context.currentFlowControl is LabeledFlowControl)
                context.exitFlowControl();

            context.exitFlowControl();
            isJumped = context.currentFlowControl.currentBranching.isJumped;

        }

    }

    /// <summary>
    /// 表示一个最顶层的语句块。
    /// </summary>
    public partial class ToplevelBlock : Block {

        /// <summary>
        /// 当前模块的输出参数列表。在函数返回前必须对这些参数赋值。
        /// </summary>
        public List<Parameter> outParameters;

        /// <summary>
        /// 获取当前语句块应该返回的类型。如果值为 var，说明根据 return 语句自动决定。
        /// </summary>
        public TypeReference expectedReturnType;

        /// <summary>
        /// 获取当前语句块正在推导的返回类型。如果不需要推导，则值为 null 。
        /// </summary>
        public TypeReference actualReturnType;

        /// <summary>
        /// 标记当前方法的迭代器状态。on: 使用迭代器，off: 不使用迭代器，unset: 状态未知。
        /// </summary>
        public State yieldState;

        /// <summary>
        /// 存储当前语句块内的所有迭代器语句。
        /// </summary>
        public List<YieldStatement> yieldStatements;

        /// <summary>
        /// 对当前语句快所有语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public void resolve(ResolveContext context, TypeReference returnType, Parameter parameters, FlowControl parent) {

            // 初始化语句块状态。
            expectedReturnType = returnType;

            // 空函数，自动生成返回默认值的代码。
            if (!Compiler.options.disallowMissingFuncBody && (statements == null || statements.Count == 0)) {

                // 检查返回值是否有效。
                if (returnType != PredefinedTypes.@void && returnType != PredefinedTypes.var) {
                    Compiler.warning(ErrorCode.none, "此函数未完成；将返回类型默认值", endLocation - 1, endLocation);
                }

                // 检查返回参数是否有效。
                for (var parameter = parameters; parameter != null; parameter = (Parameter)parameter.next) {
                    if (parameter.variableType == VariableType.outParameter) {
                        Compiler.warning(ErrorCode.none, String.Format("此函数未完成；输出参数“{0}”将赋值为类型默认值", parameter.name), parameter);
                    }
                }

                return;
            }

            // 进入执行分支。
            context.enterFlowControl(new ToplevelFlowControl(parent, this));

            // 初始化参数。
            for (var parameter = parameters; parameter != null; parameter = (Parameter)parameter.next) {
                if (parameter.variableType == VariableType.outParameter) {
                    parameter.index = ++context.variableCount;
                    if (outParameters == null) {
                        outParameters = ListObjectPool<Parameter>.alloc();
                    }
                    outParameters.Add(parameter);
                }

                context.currentFlowControl.addVariable(parameter);
            }

            // 执行所有语句。
            base.resolve(context);

            // 退出执行分支。
            isJumped = context.currentFlowControl.mergeBranchings().isJumped;
            context.exitFlowControlWithoutSave();

            // 非 void 返回的函数必须返回一个值。
            if (!isJumped && returnType != PredefinedTypes.var && returnType != PredefinedTypes.@void) {
                Compiler.error(ErrorCode.none, "此函数需要返回值", endLocation - 1, endLocation);
            }

            if (outParameters != null) {
                ListObjectPool<Parameter>.free(outParameters);
                outParameters = null;
            }

        }

    }

    #endregion

    #region ShimStatements

    /// <summary>
    /// 表示一个变量声明语句。
    /// </summary>
    public partial class VariableStatement {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public override void resolve(ResolveContext context) {
            for (var variable = variables; variable != null; variable = variable.next) {
                variable.resolve(context);
            }
        }

    }

    /// <summary>
    /// 表示一个标签语句。
    /// </summary>
    public partial class LabeledStatement {

        /// <summary>
        /// 用于存储跳转到当前语句之前的分支信息。
        /// </summary>
        public FlowControl.FlowBranching prevBranching;

        /// <summary>
        /// 标记当前标签语句的解析状态。on: 已解析，unset: 未解析，off: 同名错误。
        /// </summary>
        public State declareState;

        /// <summary>
        /// 判断当前标签是否已被使用。
        /// </summary>
        public bool isEverUsed;

        /// <summary>
        /// 获取或设置当前标签语句的状态。
        /// </summary>
        public State jumpState;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {

            // 判断标签名。

            // 如果标签已经标记解析了，说明是子级同名标签解析的。
            if (declareState == State.off) {
                Compiler.error(ErrorCode.none, String.Format("不能使用“{0}”作为标签名, 因为它已经在子级范围出现过了", label.value), this);
            } else {

                // 判断当前级或父级是否已定义。
                for (var c = context.currentFlowControl; c != null; c = c.parentControl) {
                    var cl = c.getLabel(label.value);
                    if (cl != null && cl != this) {
                        if (cl.declareState == State.on) {
                            Compiler.error(ErrorCode.none, String.Format("不能使用“{0}”作为标签名, 因为它已经在当前或父级范围出现过了", label.value), label);
                        } else {
                            // 父级变量未解析，先标记之，等待其解析后再报错。
                            cl.declareState = State.off;
                        }
                    }
                }

            }

            declareState = State.on;

            // Label 语句不需要在这里退出。
            context.enterFlowControl(new LabeledFlowControl(context.currentFlowControl, this));

            // 执行主体。
            if (body != null) {
                body.resolve(context);
            }
        }

    }

    /// <summary>
    /// 表示一个表达式语句。
    /// </summary>
    public partial class ExpressionStatement {

        /// <summary>
        /// 报告当前节点不可访问的警告。
        /// </summary>
        /// <returns>如果已输出警告信息则返回 true，否则返回 false。</returns>
        public override bool reportUnreachableCodeWarning() {
            return body.reportUnreachableCodeWarning();
        }

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {
            if (body == null) {
                return ;
            }
            body = body.resolveAsValue(context);

            // 赋值操作不需要任何返回值。
            var assignmemt = body as ResolvedStoreExpression;
            if (assignmemt != null) {
                assignmemt.returnVoid = true;
            }
        }

    }

    #endregion

    #region SelectionStatements

    /// <summary>
    /// 表示一个 if 语句。
    /// </summary>
    public partial class IfStatement {

        /// <summary>
        /// 获取解析后的条件表达式。
        /// </summary>
        public Expression resolvedCondition;

        /// <summary>
        /// 获取或设置当前则语句部分是否包含了跳转的语句。
        /// </summary>
        public bool isJumpedInThenClause;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {

            // 执行判断部分。
            resolvedCondition = condition.resolveAsValue(context, PredefinedTypes.System_Bool);

            // 进入执行分支。
            context.enterFlowControl(new SelectionFlowControl(context.currentFlowControl));

            // 执行 if 段。

            // 判断是否永远不执行。
            if (resolvedCondition == BoolConstant.@false && !context.currentFlowControl.currentBranching.isJumped) {
                thenClause.reportUnreachableCodeWarning();
                context.currentFlowControl.currentBranching.isJumped = true;
            }

            thenClause.resolve(context);

            // 记录当前 if 内是否有跳转。
            // 如果有跳转，则 if 不需要自己跳转到 else 末尾。
            isJumpedInThenClause = context.currentFlowControl.currentBranching.isJumped;

            // 执行 else 段。
            context.currentFlowControl.addBranching();
            if (elseClause != null) {

                // 判断是否永远不执行。
                if (resolvedCondition == BoolConstant.@true && !context.currentFlowControl.currentBranching.isJumped) {
                    elseClause.reportUnreachableCodeWarning();
                    context.currentFlowControl.currentBranching.isJumped = true;
                }

                elseClause.resolve(context);
            } else if (resolvedCondition == BoolConstant.@true) {
                context.currentFlowControl.currentBranching.isJumped = true;
            }

            // 退出执行分支。
            context.exitFlowControl();

        }

    }

    /// <summary>
    /// 表示一个 switch 语句。
    /// </summary>
    public partial class SwitchStatement {

        /// <summary>
        /// 获取当前解析后的条件表达式。
        /// </summary>
        public Expression resolvedCondition;

        /// <summary>
        /// 表示一个 case 段。
        /// </summary>
        public partial class CaseClause : Node {

            /// <summary>
            /// 用于存储跳转到当前语句之前的分支信息。
            /// </summary>
            public FlowControl.FlowBranching prevBranching;

            /// <summary>
            /// 获取当前 case 解析后返回的常量值。
            /// </summary>
            public Constant labelValue;

            /// <summary>
            /// 标记当前标签是否曾经使用过。
            /// </summary>
            public bool isEverUsed;

            /// <summary>
            /// 报告当前节点不可访问的警告。
            /// </summary>
            /// <returns>如果已输出警告信息则返回 true，否则返回 false。</returns>
            public override bool reportUnreachableCodeWarning() {
                return body.reportUnreachableCodeWarning();
            }

        }

        /// <summary>
        /// 获取一个 case 从句。
        /// </summary>
        /// <param name="labelValue"></param>
        /// <returns></returns>
        public CaseClause getCase(Constant labelValue) {
            for (var caseClause = caseClauses; caseClause != null; caseClause = caseClause.next) {
                if (caseClause.labelValue.Equals(labelValue)) {
                    return caseClause;
                }
            }
            return null;
        }

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {

            #region 执行 condition

            resolvedCondition = condition.resolveAsValue(context);
            if (resolvedCondition == null) {
                return;
            }

            TypeReference conditionType = resolvedCondition.resolvedType;
            TypeReference targetType = null;

            if (conditionType.memberType == MemberType.@enum) {
                targetType = conditionType;
            }

            // 判断目标类型是否合法。
            if (targetType == null) {
                foreach (var t in _acceptedSwitchTypes) {
                    if (conditionType == t) {
                        targetType = t;
                        break;
                    }
                }
            }

            // 判断目标类型是否可隐式转为支持类型。
            if (targetType == null) {
                foreach (var t in _acceptedSwitchTypes) {
                    var conversion = ResolveHelper.classifyImplicitConversion(resolvedCondition, conditionType, t);
                    if (conversion != ConversionType.none) {
                        if (targetType != null) {
                            targetType = null;
                            break;
                        }
                        resolvedCondition = ResolveHelper.applyConversion(resolvedCondition, t, conversion, State.unset, resolvedCondition);
                        targetType = t;
                        break;
                    }
                }
            }

            if (targetType == null) {
                Compiler.error(ErrorCode.none, String.Format("switch 表达式中不允许使用类型“{0}”", conditionType.fullName), resolvedCondition);
                return;
            }

            Constant conditionConstantValue = resolvedCondition as Constant;

            #endregion

            #region 预处理 caseClause.label

            // 优化空 switch。
            if (caseClauses == null) {
                Compiler.warning(ErrorCode.none, "空的 switch 块", this);
                return;
            }

            // 存储 else 分支。
            CaseClause caseElse = null;
            int errorCount = Compiler.errorCount;

            for (var caseClause = caseClauses; caseClause != null; caseClause = caseClause.next) {

                if (caseClause.label != null) {

                    // 处理 label 。
                    if ((caseClause.label = caseClause.label.resolveAsValue(context, conditionType)) == null) {
                        continue;
                    }

                    caseClause.labelValue = caseClause.label as Constant;

                    // 判断是否常量。
                    if (caseClause.labelValue == null) {
                        Compiler.error(ErrorCode.none, "无法在编译时计算 case 表达式的值", caseClause);
                        continue;
                    }

                    // 判断重复性。
                    for (var caseClause2 = caseClauses; caseClause2 != caseClause; caseClause2 = caseClause2.next) {
                        if (caseClause2.labelValue != null && caseClause2.labelValue.Equals(caseClause.labelValue)) {
                            Compiler.error(ErrorCode.none, "当前 switch 语句已经包含了相同的 case", caseClause);
                            break;
                        }
                    }

                } else {

                    // 判断重复性。
                    if (caseElse != null) {
                        Compiler.error(ErrorCode.none, "当前 switch 语句已经包含了 case else", caseClause);
                        continue;
                    }

                    caseElse = caseClause;

                }
            }

            // 处理标签存在错误。
            if (Compiler.errorCount > errorCount) {
                return;
            }

            #endregion

            #region 执行主体

            // 进入执行分支。
            context.enterFlowControl(new SwitchFlowControl(context.currentFlowControl, this));

            // 常量特殊处理。
            if (conditionConstantValue != null) {

                // 找出满足要求的 case。
                CaseClause selectedCase = caseElse;
                List<CaseClause> otherCases = ListObjectPool<CaseClause>.alloc();
                for (var caseClause = caseClauses; caseClause != null; caseClause = caseClause.next) {

                    // 值相等，说明这是需要找的 case 。
                    if (caseClause.label != null && caseClause.labelValue.Equals(conditionConstantValue)) {
                        selectedCase = caseClause;
                        continue;
                    }

                    if (caseClause.body != null) {
                        otherCases.Add(caseClause);
                    }
                }

                // 如果没有匹配任何分支直接退出。
                if (selectedCase == null) {
                    Compiler.warning(ErrorCode.none, "检测到永远不会执行 switch 语句的任何一个 case 分支", this);
                    context.exitFlowControlWithoutSave();
                    ListObjectPool<CaseClause>.free(otherCases);
                    return;
                }

                // 如果当前匹配了 caseElse 。
                bool selectedCaseIsElse = selectedCase == caseElse;

                // 使用有语句的 case 。
                while (selectedCase.body == null) {
                    selectedCase = selectedCase.next;
                }

                // 删除 else 分支。
                if (selectedCaseIsElse) {
                    otherCases.Remove(selectedCase);
                }

                // 记住之前的执行状态以备使用。
                bool wasNotJumped = !context.currentFlowControl.currentBranching.isJumped;

                // 执行选中的分支。
                selectedCase.body.resolve(context);

                // 查找是否有其它的 case 被激活执行。
                bool hasNewCaseReached;

                do {
                    hasNewCaseReached = false;
                    for (int i = 0; i < otherCases.Count; i++) {
                        var otherCase = otherCases[i];
                        if (otherCase != null && otherCase.isEverUsed) {
                            hasNewCaseReached = true;
                            context.currentFlowControl.addBranching();
                            if (otherCase.prevBranching != null) {
                                context.currentFlowControl.currentBranching.orVariableAssignmentInfos(otherCase.prevBranching);
                                context.currentFlowControl.currentBranching.isJumped = otherCase.prevBranching.isJumped;
                                otherCase.prevBranching = null;
                            }
                            otherCase.body.resolve(context);
                            otherCases[i] = null;
                        }
                    }
                } while (hasNewCaseReached);

                for (int i = 0; i < otherCases.Count; i++) {
                    var otherCase = otherCases[i];
                    if (otherCase != null) {
                        if (wasNotJumped && otherCase.reportUnreachableCodeWarning()) {
                            wasNotJumped = false;
                        }
                        context.currentFlowControl.addBranching();
                        context.currentFlowControl.currentBranching.isJumped = true;
                        otherCase.body.resolve(context);
                    }
                }

                ListObjectPool<CaseClause>.free(otherCases);
                context.exitFlowControl();
                return;

            }

            bool requireANewBranching = false;
            for (var caseClause = caseClauses; caseClause != null; caseClause = caseClause.next) {
                if (caseClause.body != null) {
                    if (requireANewBranching) {
                        context.currentFlowControl.addBranching();
                    } else {
                        requireANewBranching = true;
                    }

                    caseClause.body.resolve(context);
                }
            }

            // 如果没有 case else 段，则 switch 的信息都不需要保存。
            if (caseElse == null)
                context.exitFlowControlWithoutSave();
            else
                context.exitFlowControl();

            #endregion

        }

        static readonly TypeReference[] _acceptedSwitchTypes = new TypeReference[] {
            PredefinedTypes.System_Int32,
            PredefinedTypes.System_UInt32,
            PredefinedTypes.System_Int64,
            PredefinedTypes.System_UInt64,
            PredefinedTypes.System_String
        };

    }

    #endregion

    #region IterationStatements

    /// <summary>
    /// 表示一个 for 语句。
    /// </summary>
    public partial class ForStatement {

        /// <summary>
        /// 获取解析后的条件表达式。
        /// </summary>
        public Expression resolvedCondition;

        /// <summary>
        /// 获取解析后的条件表达式。
        /// </summary>
        public Expression resolvedIterator;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>
        /// 返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。
        /// </returns>
        public override void resolve(ResolveContext context) {

            // 执行初始化语句。
            if (initializer != null) {
                var variable = initializer as Variable;
                if (variable != null) {
                    context.addVariables(variable);
                    for (var v = variable; v != null; v = v.next) {
                        v.resolve(context);
                    }
                } else {
                    initializer = ((Expression)initializer).resolveAsValue(context);
                }
            }

            var needToReport = !context.currentFlowControl.currentBranching.isJumped;

            // 执行条件。
            if (condition != null) {
                resolvedCondition = condition.resolveAsValue(context, PredefinedTypes.System_Bool);
            }

            // 进入执行分支。
            context.enterFlowControl(new BreakableFlowControl(context.currentFlowControl));

            if (resolvedCondition == BoolConstant.@true) {
                context.currentFlowControl.currentBranching.isJumped = true;
            }
            context.currentFlowControl.addBranching();
            if (resolvedCondition == BoolConstant.@false) {
                context.currentFlowControl.currentBranching.isJumped = true;
                if (needToReport && body.reportUnreachableCodeWarning()) {
                    needToReport = false;
                }
            }

            context.enterFlowControl(new ContinuableFlowControl(context.currentFlowControl));

            // 执行主体。
            body.resolve(context);

            context.exitFlowControl();

            // 执行迭代器部分。
            if (iterator != null) {
                if (context.currentFlowControl.currentBranching.isJumped && needToReport && iterator.reportUnreachableCodeWarning()) {
                    needToReport = false;
                }

                resolvedIterator = iterator.resolveAsValue(context);
            }

            // 当前循环导致之后代码无法执行。
            context.currentFlowControl.currentBranching.isJumped = true;
            context.exitFlowControl();
        }

    }

    /// <summary>
    /// 表示一个 for in 语句。
    /// </summary>
    public partial class ForInStatement {

        /// <summary>
        /// 获取解析后的条件表达式。
        /// </summary>
        public Expression resolvedIterator;

        /// <summary>
        /// 将迭代的值转为当期迭代变量使用的转换。
        /// </summary>
        public ConversionType conversion;

        /// <summary>
        /// 获取实际使用的接口类型。
        /// </summary>
        public TypeReference resolvedInterfaceType;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public override void resolve(ResolveContext context) {

            // 解析循环变量。
            variable.resolve(context, true);
            variable.setAssigned(context);

            // 解析循环目标。
            resolvedIterator = iterator.resolveAsValue(context);
            var iteratorType = iterator.resolvedType;

            // 进入执行分支。
            context.enterFlowControl(new BreakableFlowControl(context.currentFlowControl));
            context.enterFlowControl(new ContinuableFlowControl(context.currentFlowControl));

            foreach (TypeReference requiredType in iteratorType.getAllRequiredTypes()) {
                if (requiredType.underlyingMember == PredefinedTypes.System_Collections_IEnumeratable_T && (variable.resolvedType == PredefinedTypes.var || (conversion = ResolveHelper.classifyImplicitConversion(null, resolvedInterfaceType.genericArguments[0], variable.resolvedType)) != ConversionType.none)) {
                    if (resolvedInterfaceType != null) {
                        Compiler.error(ErrorCode.none, String.Format("无法确定使用“{0}”还是“{1}”提供的迭代器", resolvedInterfaceType.fullName, requiredType.fullName), iterator);
                        break;
                    }
                    resolvedInterfaceType = requiredType;
                }
            }

            if (variable.resolvedType == PredefinedTypes.var) {
                variable.resolvedType = resolvedInterfaceType.genericArguments[0];
            }

            body.resolve(context);

            context.exitFlowControl();

            // 当前循环导致之后代码无法执行。
            context.currentFlowControl.currentBranching.isJumped = true;
            context.exitFlowControl();
        }

    }

    /// <summary>
    /// 表示一个 for to 语句。
    /// </summary>
    public partial class ForToStatement {

        /// <summary>
        /// 解析后用于比较的操作符。
        /// </summary>
        public Expression resolvedComparer;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public override void resolve(ResolveContext context) {
            context.addVariables(variable);
            variable.resolve(context);

            var resolvedEnd = end.resolveAsValue(context);
            if (resolvedEnd != null) {
                // 必须存在 from < end 的操作符重载。
                resolvedComparer = ResolveHelper.invoke(context, new ResolvedLoadVariableExpression() {
                    target = variable
                }, TokenType.lt, resolvedEnd, this);
            }

            if (iterator != null) {
                iterator = iterator.resolveAsValue(context);
            }

            // 进入执行分支。
            context.enterFlowControl(new BreakableFlowControl(context.currentFlowControl));
            context.enterFlowControl(new ContinuableFlowControl(context.currentFlowControl));

            body.resolve(context);

            context.exitFlowControl();

            // 当前循环导致之后代码无法执行。
            context.currentFlowControl.currentBranching.isJumped = true;
            context.exitFlowControl();
        }

    }

    /// <summary>
    /// 表示一个 while 语句。
    /// </summary>
    public partial class WhileStatement {

        /// <summary>
        /// 获取解析后的条件表达式。
        /// </summary>
        public Expression resolvedCondition;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>
        /// 返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。
        /// </returns>
        public override void resolve(ResolveContext context) {

            // 执行条件部分。
            resolvedCondition = condition.resolveAsValue(context, PredefinedTypes.System_Bool);

            // 进入 while break 分支。
            context.enterFlowControl(new BreakableFlowControl(context.currentFlowControl));

            // 无限循环不创建子分支，主体代码必然执行。
            if (resolvedCondition == BoolConstant.@false && !context.currentFlowControl.currentBranching.isJumped) {
                body.reportUnreachableCodeWarning();
                context.currentFlowControl.currentBranching.isJumped = true;
            }

            // 进入 while continue 分支。
            context.enterFlowControl(new ContinuableFlowControl(context.currentFlowControl));

            // 执行主体部分。
            body.resolve(context);

            // 退出 while continue 分支。
            context.exitFlowControl();

            // 当前循环导致之后代码无法执行。
            context.currentFlowControl.currentBranching.isJumped = true;

            // 退出 while break 分支。
            // 无限循环主体代码必然执行，否则直接丢弃子分支的信息。
            if (resolvedCondition == BoolConstant.@true) {
                context.exitFlowControl();
            } else {
                context.exitFlowControlWithoutSave();
            }

        }

    }

    /// <summary>
    /// 表示一个 do while 语句。
    /// </summary>
    public partial class DoWhileStatement {

        /// <summary>
        /// 获取解析后的条件表达式。
        /// </summary>
        public Expression resolvedCondition;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {

            // 进入 do 分支。
            context.enterFlowControl(new BreakableFlowControl(context.currentFlowControl));
            context.enterFlowControl(new ContinuableFlowControl(context.currentFlowControl));

            bool wasJumped = context.currentFlowControl.currentBranching.isJumped;

            // 执行主体部分。
            body.resolve(context);

            context.exitFlowControl();

            // 执行条件。
            if (context.currentFlowControl.currentBranching.isJumped && !wasJumped) {
                condition.reportUnreachableCodeWarning();
            }

            // 执行条件部分。
            resolvedCondition = condition.resolveAsValue(context, PredefinedTypes.System_Bool);

            if (resolvedCondition == BoolConstant.@true) {
                context.currentFlowControl.currentBranching.isJumped = true;
            }

            context.exitFlowControl();

        }

    }

    public partial class Iterator {
        public Block Block;
    }

    #endregion

    #region JumpStatements

    /// <summary>
    /// 表示一个 continue 语句。
    /// </summary>
    public partial class ContinueStatement {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>
        /// 返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。
        /// </returns>
        public override void resolve(ResolveContext context) {
            context.currentFlowControl.execContinue(context.currentFlowControl.currentBranching, this);
            context.currentFlowControl.currentBranching.isJumped = true;
        }

    }

    /// <summary>
    /// 表示一个 break 语句。
    /// </summary>
    public partial class BreakStatement {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>
        /// 返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。
        /// </returns>
        public override void resolve(ResolveContext context) {
            context.currentFlowControl.execBreak(context.currentFlowControl.currentBranching, this);
            context.currentFlowControl.currentBranching.isJumped = true;
        }

    }

    /// <summary>
    /// 表示一个跳转到标签的跳到语句。
    /// </summary>
    public partial class GotoLabelStatement {

        /// <summary>
        /// 当前跳转的目标。
        /// </summary>
        public LabeledStatement resolvedTarget;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>
        /// 返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。
        /// </returns>
        public override void resolve(ResolveContext context) {
            context.currentFlowControl.execGoto(context.currentFlowControl.currentBranching, this);
            context.currentFlowControl.currentBranching.isJumped = true;
        }

    }

    /// <summary>
    /// 表示一个跳转到 case 语句的跳到语句。
    /// </summary>
    public partial class GotoCaseStatement {

        /// <summary>
        /// 获取当前解析后的目标 case 段。
        /// </summary>
        public SwitchStatement.CaseClause resolvedTarget;

        /// <summary>
        /// 获取当前解析的标签值。
        /// </summary>
        public Constant labelValue;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>
        /// 返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。
        /// </returns>
        public override void resolve(ResolveContext context) {
            var label = target.resolveAsValue(context);
            labelValue = label as Constant;
            if (labelValue == null) {
                if (label != null) {
                    Compiler.error(ErrorCode.none, "无法在编译时计算标签的值", target);
                }
            } else {
                context.currentFlowControl.execGoto(context.currentFlowControl.currentBranching, this);
            }

            context.currentFlowControl.currentBranching.isJumped = true;
        }

    }

    /// <summary>
    /// 表示一个 return 语句。
    /// </summary>
    public partial class ReturnStatement {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {

            // 执行表达式。
            var currentToplevelBlock = context.currentToplevelBlock;
            var returnType = currentToplevelBlock.expectedReturnType;
            if (value != null) {
                if (returnType == PredefinedTypes.@void) {
                    value = value.resolveAsValue(context);
                    if (value == null || value.resolvedType != PredefinedTypes.@void) {
                        Compiler.error(ErrorCode.none, "此函数不需要返回值", this);
                    }
                } else {
                    value = value.resolveAsValue(context, ref returnType);
                }
            } else if (returnType == PredefinedTypes.var) {
                returnType = PredefinedTypes.@void;
            } else if (returnType != PredefinedTypes.@void) {
                Compiler.error(ErrorCode.none, String.Format("此函数需要返回“{0}”类型的对象", returnType.fullName), this);
            }

            // 推导实际的类型。
            if (currentToplevelBlock.expectedReturnType == PredefinedTypes.var) {
                currentToplevelBlock.actualReturnType = ResolveHelper.getCommonBaseType(currentToplevelBlock.actualReturnType, returnType);
            }

            // 执行 return 。

            context.currentFlowControl.execReturn(context.currentFlowControl.currentBranching, this);
            context.currentFlowControl.currentBranching.isJumped = true;
        }

    }

    /// <summary>
    /// 表示一个 yield 语句。
    /// </summary>
    public partial class YieldStatement {

        /// <summary>
        /// 获取当前迭代器块中 yield 的序号。
        /// </summary>
        public int index;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public override void resolve(ResolveContext context) {

            // 执行表达式。
            var currentToplevelBlock = context.currentToplevelBlock;

            if (currentToplevelBlock.expectedReturnType.underlyingType != PredefinedTypes.System_Collections_IEnumeratable_T) {
                if (currentToplevelBlock.expectedReturnType == PredefinedTypes.var) {
                    Compiler.error(ErrorCode.none, String.Format("在匿名函数或返回“var”的函数内无法使用 yield", PredefinedTypes.System_Collections_IEnumeratable_T.fullName), this);
                } else {
                    Compiler.error(ErrorCode.none, String.Format("在不返回“{0}”类型时无法使用 yield", PredefinedTypes.System_Collections_IEnumeratable_T.fullName), this);
                }
                return;
            }

            value = value.resolveAsValue(context, currentToplevelBlock.expectedReturnType.genericArguments[0]);

            // 执行 yield。
            context.currentFlowControl.execYield(this);
        }

    }

    /// <summary>
    /// 表示一个 throw 语句。
    /// </summary>
    public partial class ThrowStatement {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。</returns>
        public override void resolve(ResolveContext context) {

            // 执行表达式部分。
            if (value != null) {
                value = value.resolveAsValue(context);
            }

            // 执行 throw。
            context.currentFlowControl.currentBranching.isJumped = true;
        }

    }

    #endregion

    #region ExceptionStatements

    /// <summary>
    /// 表示一个 try 语句。
    /// </summary>
    public partial class TryStatement {

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        /// <returns>
        /// 返回解析后的新语句，它的所有子语句都已经被解析。如果解析出现错误则返回 null 。
        /// </returns>
        public override void resolve(ResolveContext context) {

            if (finallyClause != null) {
                context.enterFlowControl(new TryFinallyFlowControl(context.currentFlowControl));
            }

            context.enterFlowControl(new TryCatchFlowControl(context.currentFlowControl, this));

            // 执行 try
            tryClause.resolve(context);

            // 执行  catch
            bool foundAllCatch = false;
            for (var c = catchClauses; c != null; c = c.next) {

                context.currentFlowControl.addBranching();

                context.enterFlowControl(new ScopeFlowControl(context.currentFlowControl));

                if (c.variable != null) {
                    if (c.variable.name != null) {
                        context.addVariables(c.variable);
                    }
                    c.variable.resolve(context, true);
                    if (c.variable.resolvedType == PredefinedTypes.var) {
                        c.variable.resolvedType = PredefinedTypes.System_Exception;
                    } else if (!c.variable.resolvedType.getAllRequiredTypes().Contains(PredefinedTypes.System_Exception)) {
                        Compiler.error(ErrorCode.none, String.Format("catch 类型“{1}”不继承自“{0}”", PredefinedTypes.System_Exception.fullName, c.variable.resolvedType.fullName), c.variable.type);
                    }

                    for (var j = catchClauses; j != c; j = j.next) {
                        if (c.variable.resolvedType.getAllRequiredTypes().Contains(j.variable.resolvedType)) {
                            Compiler.error(ErrorCode.none, "之前的 catch 段已经捕获了包含此类型的异常", c);
                            break;
                        }
                    }
                } else {
                    if (foundAllCatch) {
                        Compiler.error(ErrorCode.none, "空参 catch 段之后不能有其它 catch", c);
                        break;
                    }
                    foundAllCatch = true;
                }

                c.body.resolve(context);

                context.exitFlowControl();
            }

            context.exitFlowControl();

            // 执行 finally
            if (finallyClause != null) {
                finallyClause.resolve(context);
                context.exitFlowControl();
            }

        }

    }

    /// <summary>
    /// 表示一个 with 语句。
    /// </summary>
    public partial class WithStatement {

        /// <summary>
        /// 获取当前的目标表达式解析后的目标。
        /// </summary>
        public Node resolvedTarget;

        /// <summary>
        /// 对当前语句执行语义分析。
        /// </summary>
        /// <param name="context">包含所有解析状态的上下文对象。</param>
        public override void resolve(ResolveContext context) {
            TypeReference resolvedType;
            var variable = target as Variable;
            if (variable != null) {
                context.addVariables(variable);
                variable.resolve(context);
                resolvedType = variable.resolvedType;
                resolvedTarget = variable;
            } else {
                resolvedTarget = ((Expression)target).resolveAsValue(context);
                if (resolvedTarget != null) {
                    resolvedType = ((Expression)resolvedTarget).resolvedType;
                } else {
                    resolvedType = null;
                }
            }

            // 判断类型是否正确。
            if (resolvedType != null) {
                if (resolvedType.underlyingMember == PredefinedTypes.System_Ptr_T) {

                } else if (!resolvedType.getAllRequiredTypes().Contains(PredefinedTypes.System_IClosable)) {
                    Compiler.error(ErrorCode.none, "with 只能适用于实现“System.IClosable”接口的对象", target);
                }
            }

            body.resolve(context);
        }

    }

    #endregion

}
